package com.sptan.ssmp.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sptan.framework.config.JwtProvider;
import com.sptan.framework.redis.RedisCache;
import com.sptan.ssmp.converter.AdminUserConverter;
import com.sptan.ssmp.domain.AdminUser;
import com.sptan.ssmp.dto.AdminUserCriteria;
import com.sptan.ssmp.dto.AdminUserDTO;
import com.sptan.ssmp.dto.auth.AuthRequest;
import com.sptan.ssmp.dto.auth.AuthResponse;
import com.sptan.ssmp.dto.auth.LoginUser;
import com.sptan.framework.core.ResultEntity;
import com.sptan.ssmp.mapper.AdminUserMapper;
import com.sptan.framework.mybatis.page.PageCriteria;
import com.sptan.ssmp.service.AdminUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 管理端用户表 服务实现类.
 * </p>
 *
 * @author lp
 * @since 2024-05-04
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class AdminUserServiceImpl extends ServiceImpl<AdminUserMapper, AdminUser> implements AdminUserService {

    /**
     * 密码加密工具类.
     */
    private final PasswordEncoder passwordEncoder;

    /**
     * JWT工具类.
     */
    private final JwtProvider jwtProvider;

    /**
     * Spring Security提供的认证管理器.
     */
    private final AuthenticationManager authenticationManager;

    private final RedisCache redisCache;

    /**
     * 保存.
     * 传入的参数提供id的话，是编辑用户, 如果id为空,是新增用户.
     *
     * @param dto the dto
     * @return the result entity
     */
    @Override
    public ResultEntity<AdminUserDTO> save(AdminUserDTO dto) {
        AdminUser entity = AdminUserConverter.INSTANCE.toEntity(dto);
        this.saveOrUpdate(entity);
        return ResultEntity.ok(AdminUserConverter.INSTANCE.toDto(entity));
    }

    /**
     * 删除.
     * 这里采用逻辑删除.
     *
     * @param id the id
     * @return the result entity
     */
    @Override
    public ResultEntity<Boolean> delete(Long id) {
        AdminUser entity = getById(id);
        if (entity == null || Objects.equals(true, entity.getDeleteFlag())) {
            return ResultEntity.error("数据不存在");
        }
        entity.setDeleteFlag(true);
        this.saveOrUpdate(entity);
        return ResultEntity.ok(true);
    }

    /**
     * 查看详情.
     *
     * @param id the id
     * @return the result entity
     */
    @Override
    public ResultEntity<AdminUserDTO> detail(Long id) {
        AdminUser entity = baseMapper.selectById(id);
        if (entity == null || Objects.equals(true, entity.getDeleteFlag())) {
            return ResultEntity.error("数据不存在");
        }
        AdminUserDTO dto = AdminUserConverter.INSTANCE.toDto(entity);
        return ResultEntity.ok(dto);
    }

    /**
     * 根据条件分页查询.
     *
     * @param criteria the criteria
     * @return the result entity
     */
    @Override
    public ResultEntity<IPage<AdminUserDTO>> search(AdminUserCriteria criteria) {
        LambdaQueryWrapper<AdminUser> wrapper = getSearchWrapper(criteria);
        IPage<AdminUser> entityPage = this.baseMapper.selectPage(PageCriteria.toPage(criteria), wrapper);
        return ResultEntity.ok(entityPage.convert(AdminUserConverter.INSTANCE::toDto));
    }

    /**
     * Gets by user name.
     *
     * @param username the username
     * @return the by user name
     */
    @Override
    public Optional<AdminUser> findByUserName(String username) {
        AdminUser adminUser = baseMapper.selectOne(new LambdaQueryWrapper<AdminUser>()
            .eq(AdminUser::getDeleteFlag, false)
            .eq(AdminUser::getUserName, username));
        if (adminUser == null) {
            return Optional.empty();
        } else {
            return Optional.of(adminUser);
        }
    }

    /**
     * Register admin user.
     *
     * @param username the username
     * @param password the password
     * @return the admin user
     */
    @Override
    public ResultEntity<AuthResponse> register(String username, String password) {
        LambdaQueryWrapper<AdminUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AdminUser::getUserName, username);
        AdminUser adminUser = baseMapper.selectOne(wrapper);
        if (adminUser != null) {
            return ResultEntity.error("已经被注册");
        }
        AdminUser record = buildAdminUser(username, password);
        this.save(record);
        LoginUser loginUser = LoginUser.builder().user(record).build();
        String token = jwtProvider.generateToken(loginUser);
        AuthResponse registerResponse = AuthResponse.builder()
            .token(token)
            .build();
        return ResultEntity.ok(registerResponse);
    }

    /**
     * Login result entity.
     *
     * @param request the request
     * @return the result entity
     */
    @Override
    public ResultEntity<AuthResponse> login(AuthRequest request) {
        authenticationManager.authenticate(
            new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword()));
        var user = findByUserName(request.getUsername())
            .orElseThrow(() -> new IllegalArgumentException("用户名或者密码不对."));
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        user.setUserIdentifier(uuid);
        redisCache.setCacheObject(uuid, user, 1, TimeUnit.HOURS);
        var jwt = jwtProvider.generateToken(uuid);
        AuthResponse authResponse = AuthResponse.builder().token(jwt).build();
        return ResultEntity.ok(authResponse);
    }

    private AdminUser buildAdminUser(String username, String password) {
        AdminUser record = new AdminUser();
        record.setUserName(username);
        record.setEmail(username);
        record.setMobile(username);
        record.setPassword(passwordEncoder.encode(password));
        return record;
    }

    /**
     * 获取查询条件.
     * @param criteria
     * @return
     */
    private LambdaQueryWrapper<AdminUser> getSearchWrapper(AdminUserCriteria criteria) {
        LambdaQueryWrapper<AdminUser> wrapper = new LambdaQueryWrapper<>();
        // 罗删除的用户默认不展示出来
        wrapper.eq(AdminUser::getDeleteFlag, false);
        if (criteria == null) {
            return wrapper;
        }
        if (StringUtils.hasText(criteria.getUserName())) {
            // 名字模糊查询
            wrapper.like(AdminUser::getUserName, "%" + criteria.getUserName() + "%");
        }
        return wrapper;
    }
}
